<?php
/**
 * @Name: AccessTokenServices.php
 * @Author: yashuai 1762910894@qq.com
 */

namespace App\Http\Services;

use App\Http\Logic\SettingsLogic;
use HugCode\WeChat\Basics\BasicWeChat;
use HugCode\WeChat\Offiaccount\OAWebApps\JsSdk;
use HugCode\WeChat\Basics\Exception\MessageException;

class AccessTokenServices
{

    private static $wechatAccount = [];

    /**
     * @Desc 获取配置
     * @return array
     * @author yashuai 1762910894@qq.com
     */
    public static function getConfig()
    {
        if (empty(self::$wechatAccount)) {
            self::$wechatAccount = [
                'appid'     => env('WECHAT_APPID', ''),
                'appsecret' => env('WECHAT_APPSECRET', ''),
            ];
        }
        return self::$wechatAccount;
    }

    /**
     * @Desc 获取access_token
     * @return array|mixed|void
     * @throws \App\Exceptions\ApiException
     * @author yashuai 1762910894@qq.com
     */
    public static function getAccessToken()
    {
        try {
            $config = self::getConfig();
            $result = SettingsLogic::instance()->getConfigure(SettingsLogic::WECHAT_TOKEN);
            $decode = self::decodeToken($result, 'AccessToken');
            if (empty($decode)) { // 未查询到记录
                $accessToken = (new BasicWeChat($config, false))->getAccessToken();
                SettingsLogic::instance()->setConfigure([
                    'key'   => SettingsLogic::WECHAT_TOKEN,
                    'value' => [
                        'AccessToken' => json_encode([
                            'access_token' => $accessToken['access_token'],
                            'expires_in'   => time() + 3600
                        ])
                    ]
                ]);
                $token = $accessToken['access_token'];
            } else {
                $token = $decode['access_token'];
            }
            $config['access_token'] = $token;
            return $config;
        } catch (MessageException $e) {
            _throw($e->getErrorCode(), $e->getErrorMessage());
        }
    }

    /**
     * @Desc 获取JsApiTicket
     * @param array $config
     * @return mixed|void
     * @throws \App\Exceptions\ApiException
     * @author yashuai 1762910894@qq.com
     */
    public static function getJsApiTicket(array $config = [])
    {
        try {
            if (empty($config)) {
                $config = self::getAccessToken();
            }
            $result = SettingsLogic::instance()->getConfigure(SettingsLogic::WECHAT_TICKET);
            $decode = self::decodeToken($result, 'JsApiTicket');
            if (empty($decode)) {  // 过期 或 获取异常
                $jsApiTicket = (new JsSdk($config))->getJsApiTicket();
                SettingsLogic::instance()->setConfigure([
                    'key'   => SettingsLogic::WECHAT_TICKET,
                    'value' => [
                        'JsApiTicket' => json_encode([
                            'ticket'     => $jsApiTicket['ticket'],
                            'expires_in' => time() + intval($jsApiTicket['expires_in']) - 10
                        ])
                    ]
                ]);
                $ticket = $jsApiTicket['ticket'];
            } else {
                $ticket = $decode['ticket'];
            }

            return $ticket;
        } catch (MessageException $e) {
            _throw($e->getErrorCode(), $e->getErrorMessage());
        }
    }


    /**
     * @Desc token转数组
     * @param array $array
     * @param string $field
     * @return bool|mixed
     * @author yashuai
     * @Time 2021/7/9 13:15
     */
    public static function decodeToken(array $array = [], string $field = '')
    {
        if (empty($array)) {
            return false;
        }
        if (!$result = _array_field($array, $field, false)) {
            return false;
        }
        try {
            $token = json_decode($result, true);
            if (!$expires = _array_field($token, 'expires_in', false)) {
                return false;
            }
            if ($expires < time()) {
                return false;
            }
            return $token;
        } catch (\Exception $e) {
            return false;
        }
    }

}
